<?php
namespace App\Common\Cla\EChat\Room;

use App\Common as com;
use App\Common\Cla\EChat\Room\ReceivePools as thisReceivePools;
use App\Common\Cla\EChat\Room as nameRoom;

class ReceivePools extends com\Cla\ClaBase {

	/**
	 * 接收池
	 * @var thisReceivePools\Item[]
	 */
	private array $receiveItemPools = [];

	/**
	 * 接收池id
	 * @var int
	 */
	private int $receivePoolsIndex = 0;

	/**
	 * @param nameRoom|\WeakReference $room
	 * @throws com\Lib\Err\BaseException\Throw_
	 * @throws com\Lib\Err\Exception
	 */
	public function __construct( nameRoom|\WeakReference $room ) {
		$this->goWeakReferencePoolOrObj()->create( 'room', $room );
		//
		parent::__construct();
	}

	public function getRoom(  ):nameRoom {
		return $this->goWeakReferencePoolOrObj()->get( 'room' );
	}

	/**
	 * 获取接收池
	 * @return ReceivePools\Item[]
	 */
	public function getReceiveItemPools():array {
		return $this->receiveItemPools;
	}

	/**
	 * 获取接收通道类
	 * @param int $receiveId
	 * @return ReceivePools\Item|null
	 */
	public function getReceiveItem( int $receiveId ):thisReceivePools\Item|null {
		return $this->receiveItemPools[ $receiveId ] ?? null;
	}

	/**
	 * @param \Closure $msgCallback
	 * @param int $receiveTimeoutS
	 * @return thisReceivePools\Item 返回接收对象
	 */
	public function add( \Closure $msgCallback, int $receiveTimeoutS ):thisReceivePools\Item {
		$receiveId = ++$this->receivePoolsIndex;
		//
		$this->receiveItemPools[ $receiveId ] = thisReceivePools\Item::makeOfNew( $this->getRoom(), $receiveId, $msgCallback, $receiveTimeoutS );
		// 开启一个自删协程
		/*
		if( $receiveTimeoutS >= 0 ){
			\Swoole\Timer::after( $receiveTimeoutS * 1000, function() use ( $receiveId ){
				$this->stopReceive( $receiveId );
			} );
		}
		*/
		//
		return $this->receiveItemPools[ $receiveId ];
	}

	/**
	 * 是否存在
	 * @param int $receiveId
	 * @return bool
	 */
	public function has( int $receiveId ):bool {
		return array_key_exists( $receiveId, $this->receiveItemPools );
	}

	/**
	 * @param int $receiveId
	 * @param int|null $waitTimeoutS 等待超时时间。单位：秒
	 * @return bool 是否已结束 [true]正常结束 [fasle]超时或已关闭
	 */
	public function waitReceive( int $receiveId, ?int $waitTimeoutS = null ):bool {
		if( ! $this->has( $receiveId ) ){
			// 不存在
			return false;
		}
		return $this->receiveItemPools[ $receiveId ]->waitReceive( $waitTimeoutS );
	}

	/**
	 * 停止接收消息(多个)
	 * @param int $receiveId 指定id
	 * @param mixed $reData 结束通知数据
	 * @return bool
	 */
	public function stopReceive( int $receiveId, mixed $reData = null ):bool {
		/*
		d([
			'stopReceive',
			$this->getRoom()->getRoomQueue()->getQueueName(),
		]);
		*/
		if( ! $this->has( $receiveId ) ){
			// 不存在
			return false;
		}
		//
		return $this->receiveItemPools[ $receiveId ]->stopReceive( $reData );
	}

	/**
	 * 停止接收消息(多个)
	 * @param array|null $receiveIds 指定id [null][默认]全部
	 * @param mixed $reData 结束通知数据
	 * @return bool
	 */
	public function stopReceives( ?array $receiveIds = null, mixed $reData = null ):bool {
		if( $receiveIds === null ){
			$receiveIds = array_keys( $this->receiveItemPools );
		}
		//
		foreach( $receiveIds as $receiveId ){
			$this->stopReceive( $receiveId, $reData );
		}
		//
		return true;
	}

	/**
	 * 删除指定回调
	 * @param int $receiveId
	 * @return bool 是否已结束 [true]正常结束 [fasle]超时或已关闭
	 */
	public function rm( int $receiveId ):bool {
		if( ! $this->has( $receiveId ) ){
			return true;
		}
		/*
		d([
			'rm',
			$this->getRoom()->getRoomQueue()->getQueueName(),
		]);
		*/
		/*
		d([
			'rm',
			count( $this->receiveItemPools )
		]);
		*/
		// 删除
		unset( $this->receiveItemPools[ $receiveId ] );
		//
		$this->ifReceiveEmptyThatStop();
		//
		return true;
	}

	/**
	 * 消息处理器清理cg
	 * @return bool
	 */
	public function cg(  ):bool {
		foreach( $this->receiveItemPools as $receive ) {
			if( $receive->isExpires() ){
				$receive->stopReceive();
			}
		}
		//
		$this->ifReceiveEmptyThatStop();
		//
		return true;
	}


	/**
	 * 检查消息处理器是否为空，为空则停止接收起
	 * @param bool
	 */
	public function ifReceiveEmptyThatStop():bool {
		/*
		d([
			'ifReceiveEmptyThatStop',
			count( $this->receiveItemPools )
		]);
		*/
		if( empty( $this->receiveItemPools ) ){
			// 没有接收回调则停止接收器
			go( function(){
				// d('停止接收器');
				$this->getRoom()->getRoomQueue()->goConsume()->stopAndWait();
				//
				// $this->getRoom()->stopReceive();
			} );
		}
		//
		return true;
	}


	// ===============================
	//
	//
	// 下面为静态方法
	//
	//
	// ===============================

	/**
	 * @param nameRoom|\WeakReference $room
	 * @return $this
	 */
	public static function makeOfNew( nameRoom|\WeakReference $room ):self {
		return self::make( $room );
	}

}
